home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Personal Computer World 2009 February
/
PCWFEB09.iso
/
Software
/
Resources
/
Burning & Media
/
GB-PVR 1.2.13
/
GBPVR10213.msi
/
Cabs.w1.cab
/
Download.aspx.cs463
< prev
next >
Wrap
Text File
|
2007-07-18
|
16KB
|
458 lines
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.Remoting.Contexts;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Xml;
using GBPVRSchedule;
using Microsoft.Win32;
using System.Drawing;
using Microsoft.Win32;
using GBPVR.Public;
using ICSharpCode.SharpZipLib.Zip;
namespace gbweb
{
/// <summary>
/// Summary description for Download.
/// </summary>
public class Download : IRequiresSessionState, IHttpHandler
{
private const int buffersize = 500000; // bytes (this is size of packet)
private const int bufferdelay = 100; // milliSeconds (this is time between end of packet n, and start of packet n + 1)
// Where Bps = bytes/sec:
// buffersize * bufferdelay gives us our max download rate of 5MBps.
// (very roughly because we delay between packets (start2-end1), and don't count time between the start of packets (start2-start1)
// Moonlight encoder default is VBR with an average of 0.4MBps, and max of 0.9MBps.
// The maximum rate possible that Moonlight supports is 1.5MBps.
public enum InternalFiles
{
Log = -1,
LibraryFile = -2,
LiveTV = -3,
LibraryFolder = -4,
ChannelIcon = -5,
Photo = -6,
ModifiedPhoto = -7
}
#region IHttpHandler Members
public void ProcessRequest(HttpContext context)
{
string path = context.Request.PathInfo.TrimStart('/');
string[] ridInfo = path.Split(',');
int rid = Convert.ToInt32(ridInfo[0]);
bool direct = ridInfo[1] == "1";
path = HttpUtility.UrlDecode(context.Request.Url.Query.TrimStart('?'));
ProcessDownload(context.Request, context.Response, direct, rid, path);
}
public bool IsReusable
{
get
{
return true;
}
}
#endregion
#region GetDownloadUrl
public static string GetDownloadUrl(bool anon, bool direct, InternalFiles internalType)
{
return GetDownloadUrl(anon, direct, (int)internalType);
}
public static string GetDownloadUrl(bool anon, bool direct, InternalFiles internalType, string path)
{
return GetDownloadUrl(anon, direct, (int)internalType, path);
}
public static string GetDownloadUrl(bool anon, bool direct, int rid)
{
return GetDownloadUrl(anon, direct, rid, null);
}
public static string GetDownloadUrl(bool anon, bool direct, int rid, string path)
{
string url;
if (anon)
{
url = "public/download.aspx?rid=" + PublicDownload.Serialize(rid);
if (path != null) url += "&path=" + PublicDownload.Serialize(path);
if (direct) url += "&mode=1";
}
else
{
url = "public/download.ashx/" + rid.ToString() + (direct ? ",1" : ",0");
if (path != null) url += "?" + path;
}
return url;
}
#endregion
#region ProcessDownload
public static void ProcessDownload(HttpRequest Request, HttpResponse Response, bool direct, int rid, string path)
{
Schedule scheduleHelper = Global.Schedule;
string fileName = null;
string contentType = null;
bool attachment = true;
bool seekable = true;
ScheduledRecording recording = null;
switch (rid)
{
case (int)InternalFiles.Log:
string logfolder = typeof(GBPVR.Public.ScheduledRecording).Assembly.GetModules()[0].FullyQualifiedName;
logfolder = logfolder.Substring(0, logfolder.LastIndexOf(@"\")) + "\\logs";
string logname = AppDomain.CurrentDomain.FriendlyName + ".log";
fileName = Path.Combine(logfolder, logname);
contentType = "text/plain";
seekable = false;
attachment = false;
break;
case (int)InternalFiles.LibraryFile:
try
{
fileName = Library.GetRealPath(path);
}
catch
{
return;
}
break;
case (int)InternalFiles.LibraryFolder:
handleLibraryFolder(Request, Response, direct, path);
break;
case (int)InternalFiles.LiveTV:
string[] tuners = Info.GetRecordingService().getTunerStatus();
string currentStatus = tuners[Convert.ToInt32(path)];
Match match = Info.liveTVRegex.Match(currentStatus);
XmlNode node = Global.Config.SelectSingleNode("/settings/LiveTVDirectory");
if ((node != null) && (match.Captures.Count == 1))
{
fileName = Path.Combine(node.InnerText, match.Groups[1].ToString());
}
seekable = false;
break;
case (int)InternalFiles.ChannelIcon:
fileName = Path.Combine(Path.Combine(Global.Settings.GetInstallDir(), @"media\ChannelLogos\"), path);
break;
case (int)InternalFiles.Photo:
//This means we want to stream a photo that does not need to be rotated
//Deserialize the passed path
fileName = (string) PublicDownload.Deseralize(path);
break;
case (int)InternalFiles.ModifiedPhoto:
//This means we want to stream a photo that someone has requested to rotate.
//Deserialize the passed path
fileName = (string)PublicDownload.Deseralize(path);
//The path contains all the parms needed to find, size and rotate the image so each gets split out into
//an array for easy access
//0 = filename, 1 = desired heigth, 2 = desired width, 3 = rotation option
string[] parm = fileName.Split('~');
ModifyPhoto(Response, parm[0], Convert.ToInt32(parm[1]), Convert.ToInt32(parm[2]), Convert.ToInt32(parm[3]));
//Since the above already streamed the image then we are done here
return;
break;
default:
ScheduledRecording scheduledRecording = scheduleHelper.GetScheduledRecordingByOID(rid);
if (scheduledRecording != null)
{
recording = scheduledRecording;
fileName = recording.getFileName();
}
break;
}
if (fileName == null) return;
Response.Clear();
if ((!direct) && (attachment))
{
int seconds = -1;
if (recording != null) seconds = (int)((TimeSpan)(recording.getEndTime() - recording.getStartTime())).TotalSeconds;
Response.AppendHeader("Content-Type", "audio/mpegurl");
Response.AppendHeader("Content-Disposition", "attachment; filename=\"" + Path.GetFileNameWithoutExtension(fileName) + "." + Global.Settings.playlistExtension + "\"");
Response.Write("#EXTM3U\r\n");
Response.Write("#EXTINF:" + seconds + "," + Path.GetFileNameWithoutExtension(fileName) + "\r\n");
string url = Request.Url.ToString().Replace(
Request.Url.Scheme + Uri.SchemeDelimiter + Request.Url.Authority,
Request.Url.Scheme + Uri.SchemeDelimiter + Request.Headers["Host"]);
url = url.Substring(0, url.IndexOf("public/download.ashx"));
url += GetDownloadUrl(true, true, rid, path);
Response.Write(url + "\r\n");
Response.End();
return;
}
try
{
RegistryKey fileTypeKey = Registry.ClassesRoot.OpenSubKey(Path.GetExtension(fileName));
string autocontentType = (string)fileTypeKey.GetValue("Content Type");
fileTypeKey.Close();
if (autocontentType != null) contentType = autocontentType;
}
catch
{
}
if (contentType != null)
{
Response.AppendHeader("Content-Type", contentType);
}
Response.Buffer = false;
Stream infile = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
long startbyte = 0;
long stopbyte = infile.Length - 1;
string range = Request.Headers["Range"];
if (range != null)
{
Response.StatusCode = 206;
string[] info = range.Split('=', '-');
if ((info.Length > 1) && (info[1].Length > 0))
startbyte = Convert.ToInt64(info[1]);
if ((info.Length > 2) && (info[2].Length > 0))
stopbyte = Convert.ToInt64(info[2]);
Response.AppendHeader("Content-Range", "bytes " + startbyte.ToString() + "-" + stopbyte.ToString() + "/" + infile.Length.ToString());
}
long length = stopbyte - startbyte + 1;
if (attachment)
Response.AppendHeader("Content-Disposition", "attachment; filename=\"" + Path.GetFileName(fileName) + "\"");
else
Response.AppendHeader("Content-Disposition", "inline; filename=\"" + Path.GetFileName(fileName) + "\"");
if (seekable)
{
Response.AppendHeader("Accept-Ranges", "bytes");
try
{
Response.AppendHeader("Content-Length", length.ToString());
}
catch (OverflowException)
{
// ugh, .Net v1.1 defined the Content-Length as an Int32.
Response.AppendHeader("Content-Length", Int32.MaxValue.ToString());
}
}
Response.AppendHeader("icy-name", Path.GetFileName(fileName));
Response.Cache.SetLastModified(File.GetLastWriteTime(fileName));
Response.Cache.SetExpires(DateTime.Now.AddDays(1));
infile.Position = startbyte;
WriteLargeFileSlowly(Response, infile, Response.OutputStream, rid.ToString());
Response.End();
}
private static void WriteLargeFileSlowly(HttpResponse Response, Stream infile, Stream outfile, string logID)
{
// Response.WriteFile(fileName, startbyte, length);
// WriteFile doesn't allow us to control the max download speed.
// Also in .Net v1.1 / Cassini it doesn't allow > 2GB files to be downloaded.
byte[] buffer = new byte[buffersize];
int readcount = infile.Read(buffer, 0, buffersize);
while (readcount > 0)
{
try
{
outfile.Write(buffer, 0, readcount);
}
catch (Exception ex)
{
Logger.Error("[" + logID + "]: outfile.Write Exception: " + ex.ToString());
break;
}
Thread.Sleep(bufferdelay);
readcount = infile.Read(buffer, 0, buffersize);
if (!Response.IsClientConnected)
{
Logger.Error("[" + logID + "]: Client Not Connected");
break;
}
}
if (readcount != 0) Logger.Error("[" + logID + "]: Read Count Non-Zero");
infile.Close();
}
public static string streamLibraryFolder(HttpRequest Request, string vpath)
{
string[] pathparts = vpath.Split(new char[] { '/' }, 3);
Regex fileFilter = Library.GetRegex(pathparts[0]);
string path = Library.GetRealPath(vpath);
string[] filenames = Directory.GetFiles(path);
Array.Sort(filenames);
string tmpDir = Environment.GetEnvironmentVariable("ALLUSERSPROFILE");
FileInfo playlist = new FileInfo(tmpDir + "\\playlist.m3u");
StreamWriter sw = playlist.CreateText();
//sw.WriteLine("Content-Type", "audio/mpegurl");
//sw.WriteLine("Content-Disposition", "attachment; filename=\"" + Path.GetFileName(Path.GetDirectoryName(path)) + "." + Global.Settings.playlistExtension + "\"");
sw.Write("#EXTM3U\r\n");
string urlroot = Request.Url.ToString().Replace(
Request.Url.Scheme + Uri.SchemeDelimiter + Request.Url.Authority,
Request.Url.Scheme + Uri.SchemeDelimiter + Request.Headers["Host"]);
if (urlroot.Contains("Player.aspx"))
{
urlroot = urlroot.Substring(0, urlroot.IndexOf("Player.aspx"));
}
foreach (string filename in filenames)
{
if ((filename == Path.GetFullPath(filename)) && (fileFilter.IsMatch(filename)))
{
sw.Write("#EXTINF:0," + Path.GetFileNameWithoutExtension(filename) + "\r\n");
//string url =
// urlroot + GetDownloadUrl(true, true, Download.InternalFiles.LibraryFile, vpath + Path.GetFileName(filename));
sw.Write(filename + "\r\n");
}
}
sw.Close();
return(playlist.Name);
}
private static void handleLibraryFolder(HttpRequest Request, HttpResponse Response, bool direct, string vpath)
{
string[] pathparts = vpath.Split(new char[] {'/'}, 3);
Regex fileFilter = Library.GetRegex(pathparts[0]);
string path = Library.GetRealPath(vpath);
string[] filenames = Directory.GetFiles(path);
Array.Sort(filenames);
if (!direct)
{
Response.AppendHeader("Content-Type", "audio/mpegurl");
Response.AppendHeader("Content-Disposition", "attachment; filename=\"" + Path.GetFileName(Path.GetDirectoryName(path)) + "." + Global.Settings.playlistExtension + "\"");
Response.Write("#EXTM3U\r\n");
string urlroot = Request.Url.ToString().Replace(
Request.Url.Scheme + Uri.SchemeDelimiter + Request.Url.Authority,
Request.Url.Scheme + Uri.SchemeDelimiter + Request.Headers["Host"]);
urlroot = urlroot.Substring(0, urlroot.IndexOf("public/download.ashx"));
foreach (string filename in filenames)
{
if ((filename == Path.GetFullPath(filename)) && (fileFilter.IsMatch(filename)))
{
Response.Write("#EXTINF:0," + Path.GetFileNameWithoutExtension(filename) + "\r\n");
string url =
urlroot + GetDownloadUrl(true, true, Download.InternalFiles.LibraryFile, vpath + Path.GetFileName(filename));
Response.Write(url + "\r\n");
}
}
}
else
{
Response.AppendHeader("Content-Type", "application/zip");
Response.AppendHeader("Content-Disposition", "attachment; filename=\"" + Path.GetFileName(Path.GetDirectoryName(path)) + ".zip\"");
ZipOutputStream s = new ZipOutputStream(Response.OutputStream);
s.SetLevel(0);
foreach (string filename in filenames)
{
if ((filename == Path.GetFullPath(filename)) && (fileFilter.IsMatch(filename)))
{
FileStream fs = File.OpenRead(filename);
ZipEntry entry = new ZipEntry(Path.Combine(Path.GetFileName(Path.GetDirectoryName(filename)), Path.GetFileName(filename)));
entry.Size = fs.Length;
s.PutNextEntry(entry);
WriteLargeFileSlowly(Response, fs, s, filename);
fs.Close();
}
}
s.Finish();
s.Close();
}
Response.End();
}
private static void ModifyPhoto(HttpResponse Response, string filepath, int H, int W, int R)
{
//Create the image from the file location
System.Drawing.Image image = System.Drawing.Image.FromFile(filepath);
//Rotate the image based on what the user selected
switch (R)
{
case 1:
{
image.RotateFlip(RotateFlipType.Rotate90FlipNone);
break;
}
case 2:
{
image.RotateFlip(RotateFlipType.Rotate180FlipNone);
break;
}
case 3:
{
image.RotateFlip(RotateFlipType.Rotate270FlipNone);
break;
}
}
// create a new image that matches the size that the user wants
System.Drawing.Image thumbnailImage = image.GetThumbnailImage(W, H, new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback), IntPtr.Zero);
//Write (save) the new image back to the browser....in this case it is filling the image control
thumbnailImage.Save(Response.OutputStream, ImageFormat.Jpeg);
//Celanup
image.Dispose();
thumbnailImage.Dispose();
Response.Flush();
}
public static bool ThumbnailCallback()
{
return true;
}
#endregion
}
}